using System;
using System.Collections.Generic;
using System.Web.Mvc;
using TfsReports.Web.Extensions;
using TfsReports.Web.Helpers;
using TfsReports.Web.Models;

namespace TfsReports.Web.Controllers
{
    public class ChurnController : Controller
    {
        public ChurnController()
        {
            TempDataProvider = new NoTempDataProvider();
        }

        /// <summary>
        /// Generates an Index view of <see cref="Churn"/>
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="start">The start.</param>
        /// <param name="stop">The stop.</param>
        /// <param name="personId">The person id.</param>
        /// <returns></returns>
        /// <example>GET: /Churn/</example>
        public ActionResult Index(int? page, int? pageSize, DateTime? start, DateTime? stop, int? personId)
        {
            bool stopAtEndOfDay = false;
            int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
            var churns = TfsWarehouse.GetAllChurns();
            churns.Sort((c1, c2) => c2.Date.CompareTo(c1.Date));
            if (!stop.HasValue)
                stop = churns[0].Date;
            if (!start.HasValue)
                start = churns[churns.Count - 1].Date;
            if (stop == ((DateTime)stop).Date)
            {
                stop = ((DateTime) stop).AddDays(1).AddSeconds(-1);
                stopAtEndOfDay = true;
            }
            List<Person> people = Person.GetAll(churns);
            ViewData["Title"] = string.Format("Code Churn from {0} to {1} for {2}", stopAtEndOfDay ? ((DateTime)start).ToString("yyyy-MM-dd") : ((DateTime)start).ToString("yyyy-MM-dd HH:mm"), stopAtEndOfDay ? ((DateTime)stop).ToString("yyyy-MM-dd") : ((DateTime)stop).ToString("yyyy-MM-dd HH:mm"), personId.HasValue ? people.Find(p => p.Id == personId).Title : "all contributors");
            var filteredChurns = personId.HasValue
                ? churns.FindAll(c => c.Date > start && c.Date < stop && c.Person.Id == personId)
                : churns.FindAll(c => c.Date > start && c.Date < stop);
            filteredChurns.Sort((c1, c2) => c1.Id.CompareTo(c2.Id));
            return View(filteredChurns.ToPagedList(currentPageIndex, pageSize ?? 10));
        }

        /// <summary>
        /// Generates an Details view of <see cref="ChurnController"/>
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        /// <example>GET: /Churn/5</example>
        public ActionResult Details(int? id)
        {
            return View(TfsWarehouse.GetAllChurns().Find(c => c.Id == id));
        }

        /// <summary>
        /// Generates an Graph view of <see cref="Churn"/>
        /// </summary>
        /// <param name="start">The start.</param>
        /// <param name="stop">The stop.</param>
        /// <returns></returns>
        /// <example>GET: /Churn/Graph/</example>
        public ActionResult Graph(DateTime? start, DateTime? stop)
        {
            List<string> colours = new List<string> { "4d89f9", "008C7E", "000000" };
            const string apiUrl = "http://chart.apis.google.com/chart";
            Dictionary<string, string> parameters = new Dictionary<string, string>
                                                        {
                                                            {"cht", "bvg"},
                                                            {"chs", "400x200"},
                                                            {"chbh", "a"},
                                                            {"chco", string.Empty},
                                                            {"chd", "t:"},
                                                            {"chdl", string.Empty}
                                                        };
            if(!start.HasValue && !stop.HasValue)
            {
                start = DateTime.Now.Date.AddDays(-7);
                stop = DateTime.Now.Date;
            }
            List<DateTime> dates = new List<DateTime>();
            Dictionary<int, Person> persons = new Dictionary<int, Person>();
            var churns = TfsWarehouse.GetAllChurns().FindAll(c => c.Date > start && c.Date < stop);
            churns.ForEach(c=> {
                                   if(!dates.Contains(c.Date.Date))
                                       dates.Add(c.Date.Date);
                                   if(!persons.ContainsKey(c.Person.Id))
                                       persons.Add(c.Person.Id, c.Person);
                               });
            dates.Sort();
            Dictionary<DateTime, Dictionary<int, List<Change>>> data = new Dictionary<DateTime, Dictionary<int, List<Change>>>();
            dates.ForEach(d =>
                              {
                                  data.Add(d, new Dictionary<int, List<Change>>());
                                  foreach (KeyValuePair<int, Person> pair in persons)
                                      data[d].Add(pair.Value.Id, new List<Change>());
                              });
            churns.ForEach(churn => data[churn.Date.Date][churn.Person.Id].Add(churn.Change));

            List<string> chd = new List<string>();
            foreach (Person person in persons.Values)
            {
                int personId = person.Id;
                List<int> dailyTotals = new List<int>();
                dates.ForEach(date =>
                {
                    int total = 0;
                    data[date][personId].ForEach(change => total += change.LinesAdded);
                    dailyTotals.Add(total);
                });
                List<string> s = new List<string>();
                dailyTotals.ForEach(v => s.Add(v.ToString()));
                chd.Add(string.Join(",", s.ToArray()));
            }

            parameters["chd"] += string.Join("|", chd.ToArray());

            List<string> personTitles = new List<string>();
            foreach (Person person in persons.Values)
                personTitles.Add(person.Title);
            parameters["chdl"] = string.Join("|", personTitles.ToArray());
            parameters["chco"] = string.Join("|", colours.ToArray());
            
            List<string> queryString = new List<string>();
            foreach (KeyValuePair<string, string> pair in parameters)
                queryString.Add(string.Format("{0}={1}", pair.Key, pair.Value));
            return PartialView("Graph", string.Format("{0}?{1}", apiUrl, string.Join("&", queryString.ToArray())));
        }

        /// <summary>
        /// Generates an Plot view of <see cref="Churn"/>
        /// </summary>
        /// <param name="start">The start.</param>
        /// <param name="stop">The stop.</param>
        /// <param name="qualifier">The qualifier.</param>
        /// <returns></returns>
        /// <example>GET: /Churn/Plot/</example>
        public ActionResult Plot(DateTime? start, DateTime? stop, string qualifier)
        {
            if (!start.HasValue || !stop.HasValue)
            {
                start = DateTime.Now.Date.AddDays(-21);
                stop = DateTime.Now.Date;
            }
            ViewData["start"] = ((DateTime)start).ToString("yyyy-MM-dd");
            ViewData["stop"] = ((DateTime)stop).ToString("yyyy-MM-dd");
            if (string.IsNullOrEmpty(qualifier))
                qualifier = "Commits";
            ViewData["Qualifier"] = new SelectList( new[] { "Commits", "Churn", "LinesAdded", "LinesModified", "LinesDeleted" }, qualifier);
            ViewData["Title"] = string.Format("Code {0} from {1:g} to {2:g}", qualifier, start, stop);
            return View("Plot", new ChurnTable(TfsWarehouse.GetAllChurns().FindAll(c => c.Date > start && c.Date.Date <= stop)));
        }
    }
}
